home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload Trio 2 / Shareware Overload Trio Volume 2 (Chestnut CD-ROM).ISO / dir24 / psi110g.zip / TCPHDR.C < prev    next >
C/C++ Source or Header  |  1994-04-17  |  5KB  |  162 lines

  1. /* TCP header conversion routines
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  */
  4. #include "global.h"
  5. #include "mbuf.h"
  6. #include "iface.h"
  7. #include "tcp.h"
  8. #include "ip.h"
  9. #include "internet.h"
  10.   
  11. /* Convert TCP header in host format into mbuf ready for transmission,
  12.  * link in data (if any). If ph != NULL, compute checksum, otherwise
  13.  * take checksum from tcph->checksum
  14.  */
  15. struct mbuf *
  16. htontcp(tcph,data,ph)
  17. register struct tcp *tcph;
  18. struct mbuf *data;
  19. struct pseudo_header *ph;
  20. {
  21.     int16 hdrlen;
  22.     struct mbuf *bp;
  23.     register char *cp;
  24.   
  25.     hdrlen =  TCPLEN;
  26.     if(tcph->optlen > 0 && tcph->optlen <= TCP_MAXOPT){
  27.         hdrlen += tcph->optlen;
  28.     } else if(tcph->mss != 0){
  29.         hdrlen += MSS_LENGTH;
  30.     }
  31.     if((bp = pushdown(data,hdrlen)) == NULLBUF){
  32.         free_p(data);
  33.         return NULLBUF;
  34.     }
  35.     cp = bp->data;
  36.     cp = put16(cp,tcph->source);
  37.     cp = put16(cp,tcph->dest);
  38.     cp = put32(cp,tcph->seq);
  39.     cp = put32(cp,tcph->ack);
  40.     *cp++ = hdrlen << 2;    /* Offset field */
  41.     *cp = 0;
  42.     if(tcph->flags.congest)
  43.         *cp |= 64;
  44.     if(tcph->flags.urg)
  45.         *cp |= 32;
  46.     if(tcph->flags.ack)
  47.         *cp |= 16;
  48.     if(tcph->flags.psh)
  49.         *cp |= 8;
  50.     if(tcph->flags.rst)
  51.         *cp |= 4;
  52.     if(tcph->flags.syn)
  53.         *cp |= 2;
  54.     if(tcph->flags.fin)
  55.         *cp |= 1;
  56.     cp++;
  57.     cp = put16(cp,tcph->wnd);
  58.     if(ph == NULLHEADER){
  59.         /* Use user-supplied checksum */
  60.         cp = put16(cp,tcph->checksum);
  61.     } else {
  62.         /* Zero out checksum field for later recalculation */
  63.         *cp++ = 0;
  64.         *cp++ = 0;
  65.     }
  66.     cp = put16(cp,tcph->up);
  67.   
  68.     /* Write options, if any */
  69.     if(hdrlen > TCPLEN){
  70.         if(tcph->optlen > 0)
  71.             memcpy(cp,tcph->options,tcph->optlen);
  72.         else if(tcph->mss != 0){
  73.             *cp++ = MSS_KIND;
  74.             *cp++ = MSS_LENGTH;
  75.             cp = put16(cp,tcph->mss);
  76.         }
  77.     }
  78.     /* Recompute checksum, if requested */
  79.     if(ph != NULLHEADER)
  80.         put16(&bp->data[16],cksum(ph,bp,ph->length));
  81.   
  82.     return bp;
  83. }
  84. /* Pull TCP header off mbuf */
  85. int
  86. ntohtcp(tcph,bpp)
  87. register struct tcp *tcph;
  88. struct mbuf **bpp;
  89. {
  90.     int hdrlen,i,optlen,kind;
  91.     register int flags;
  92.     char hdrbuf[TCPLEN],*cp;
  93.   
  94.     i = pullup(bpp,hdrbuf,TCPLEN);
  95.     /* Note that the results will be garbage if the header is too short.
  96.      * We don't check for this because returned ICMP messages will be
  97.      * truncated, and we at least want to get the port numbers.
  98.      */
  99.     tcph->source = get16(&hdrbuf[0]);
  100.     tcph->dest = get16(&hdrbuf[2]);
  101.     tcph->seq = get32(&hdrbuf[4]);
  102.     tcph->ack = get32(&hdrbuf[8]);
  103.     hdrlen = (hdrbuf[12] & 0xf0) >> 2;
  104.     flags = hdrbuf[13];
  105.     tcph->flags.congest = flags & 64;
  106.     tcph->flags.urg = flags & 32;
  107.     tcph->flags.ack = flags & 16;
  108.     tcph->flags.psh = flags & 8;
  109.     tcph->flags.rst = flags & 4;
  110.     tcph->flags.syn = flags & 2;
  111.     tcph->flags.fin = flags & 1;
  112.     tcph->wnd = get16(&hdrbuf[14]);
  113.     tcph->checksum = get16(&hdrbuf[16]);
  114.     tcph->up = get16(&hdrbuf[18]);
  115.     tcph->mss = 0;
  116.     tcph->optlen = hdrlen - TCPLEN;
  117.   
  118.     /* Check for option field. Only space for one is allowed, but
  119.      * since there's only one TCP option (MSS) this isn't a problem
  120.      */
  121.     if(i < TCPLEN || hdrlen < TCPLEN)
  122.         return -1;  /* Header smaller than legal minimum */
  123.     if(tcph->optlen == 0)
  124.         return (int)hdrlen; /* No options, all done */
  125.   
  126.     if(tcph->optlen > len_p(*bpp)){
  127.         /* Remainder too short for options length specified */
  128.         return -1;
  129.     }
  130.     pullup(bpp,tcph->options,tcph->optlen); /* "Can't fail" */
  131.     /* Process options */
  132.     for(cp=tcph->options,i=tcph->optlen; i > 0;){
  133.         kind = *cp++;
  134.         /* Process single-byte options */
  135.         switch(kind){
  136.             case EOL_KIND:
  137.                 i--;
  138.                 cp++;
  139.                 return (int)hdrlen; /* End of options list */
  140.             case NOOP_KIND:
  141.                 i--;
  142.                 cp++;
  143.                 continue;   /* Go look for next option */
  144.         }
  145.         /* All other options have a length field */
  146.         optlen = uchar(*cp++);
  147.   
  148.         /* Process valid multi-byte options */
  149.         switch(kind){
  150.             case MSS_KIND:
  151.                 if(optlen == MSS_LENGTH){
  152.                     tcph->mss = get16(cp);
  153.                 }
  154.                 break;
  155.         }
  156.         optlen = max(2,optlen); /* Enforce legal minimum */
  157.         i -= optlen;
  158.         cp += optlen - 2;
  159.     }
  160.     return (int)hdrlen;
  161. }
  162.